Skip to content

audit: bead/mcb-o96i-16-hook-commit-recovery-v3 -> main - #166

Closed
marlon-costa-dc wants to merge 10 commits into
developfrom
bead/mcb-o96i-16-hook-commit-recovery-v3
Closed

audit: bead/mcb-o96i-16-hook-commit-recovery-v3 -> main#166
marlon-costa-dc wants to merge 10 commits into
developfrom
bead/mcb-o96i-16-hook-commit-recovery-v3

Conversation

@marlon-costa-dc

Copy link
Copy Markdown
Collaborator

GitFlow audit verdict (automated 2026-08-02)

  • ahead of main: 9 commits | behind: 136
  • merge probe vs origin/main: clean
  • bead: mcb-o96i
  • worktree: /home/marlonsc/mcb/.worktrees/mcb-o96i-16-hook-commit-recovery-v3

Verdict: KEEP-OPEN for review — pushed by gitflow audit; not auto-merged per policy.

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

@coderabbitai

coderabbitai Bot commented Aug 2, 2026

Copy link
Copy Markdown

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: cbc33426-7277-4510-a994-427f8aa8298e

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Recoverable checkpoint of in-flight work. Not a delivery; gates deferred.
Origin branch: bead/mcb-o96i-16-hook-commit-recovery-v3

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

17 issues found across 14 files

Confidence score: 2/5

  • In scripts/lib/mcb.sh, the staged-check path for Cargo.toml/Cargo.lock builds an invalid cargo fmt invocation (--workspace in the wrong position), so commits that touch manifests/lockfiles can fail the gate outright — adjust the fmt command construction so workspace checks use supported Cargo fmt argument ordering.
  • scripts/lib/mcb.sh currently validates working-tree state instead of the staged snapshot, and package derivation skips manifest/build/non-src target changes, so broken staged Rust can slip through pre-commit and regress CI/mainline quality — run checks against an index materialization (or fail on staged/unstaged divergence) and include those crate paths in package selection.
  • Submodule sync behavior in scripts/lib/mcb.sh is brittle: make sub WHAT=sync can hang forever on POSIX /bin/sh due to read -d, and partially materialized submodules may be treated as complete, leaving tracked files missing — switch to a POSIX-safe reader (or explicitly invoke Bash) and verify/restore missing indexed paths file-by-file.
  • Workspace command tooling has multiple reliability gaps across scripts/lib/workspace_command.py and scripts/lib/workspace.py: missing toml causes dispatcher import failure, empty shim env vars can add . to PATH, and help/dry-run/validation errors may exit without user-visible guidance — provision the runtime dependency, treat empty shim overrides as unset, and always print rendered help/error output before returning.
Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="scripts/hooks/pre-commit">

<violation number="1" location="scripts/hooks/pre-commit:10">
P3: Published pre-commit instructions still promise lint and architecture validation; update them to describe the staged-only gate so developers do not rely on checks this hook no longer runs.</violation>
</file>

<file name="Makefile">

<violation number="1" location="Makefile:39">
P3: The new check phases (staged/hooks/guard) are not reflected in AGENTS.md/README.md, which still list check WHAT as fmt|lint|validate|audit|udeps|coverage|qlty|all. Since those docs are embedded as agent/reviewer context, updating them keeps the documented surface in sync with the fact that the phases already work here.</violation>
</file>

<file name="scripts/lib/workspace.py">

<violation number="1" location="scripts/lib/workspace.py:19">
P2: An explicitly empty `WORKSPACE_MISE_SHIMS`/`MISE_SHIMS` adds `.` to dispatched-command `PATH`, allowing executables in the working tree to shadow system tools. Treat empty overrides as unset before constructing the `Path`.</violation>
</file>

<file name="scripts/lib/workspace_command.py">

<violation number="1" location="scripts/lib/workspace_command.py:20">
P1: Every dispatcher invocation fails at import when its required `toml` package is not preinstalled; declare and provision this runtime dependency for the workspace Python environment.</violation>

<violation number="2" location="scripts/lib/workspace_command.py:185">
P2: Help, action options, and mutation dry-runs exit successfully without displaying any guidance because every corresponding branch returns before emitting its `render_*` result. Print the appropriate rendered text before these returns.</violation>

<violation number="3" location="scripts/lib/workspace_command.py:185">
P3: This statement is a no-op: it calls `os.environ.get("WHAT", "").strip()` and discards the result. It looks like a leftover line from an earlier help-rendering draft, and the very next line returns 0, so this has zero effect. Safe to delete.</violation>

<violation number="4" location="scripts/lib/workspace_command.py:188">
P2: Invalid invocations fail with exit code 2 but no diagnostic, hiding required parameters and metadata errors; print the caught `RegistryError` to stderr before returning.</violation>

<violation number="5" location="scripts/lib/workspace_command.py:205">
P2: The dry-run path for mutating commands returns 0 with no user-facing feedback, and the dedicated `render_dry_run()` helper defined at line 616 is never called anywhere in the module. The advertised framework behavior ("Dry-run: sem APPLY=Y, o dispatcher nao executa a acao" plus the render_dry_run DRY-RUN banner) is disconnected from the execution path: a user running a mutating command without `APPLY=Y` sees no indication that nothing was executed. Either emit `render_dry_run(...)` on this branch, or remove the never-referenced rendering helpers.</violation>

<violation number="6" location="scripts/lib/workspace_command.py:360">
P2: Malformed marked command headers can be silently excluded from validation because `has_header` treats parse errors like an absent header. Return false only for the explicit no-header case and propagate malformed-header errors.</violation>
</file>

<file name="scripts/lib/tests/test-hooks.sh">

<violation number="1" location="scripts/lib/tests/test-hooks.sh:71">
P3: The `timeout` stub's `*[smhd]` pattern swallows any argument ending in s/m/h/d, not only the duration token. It only works because `cargo` is always the first word after the timeout options, so consider narrowing the match to duration-shaped args (e.g. `*[0-9][smhd]`) so a future reorder or option doesn't silently drop a real argument and skew the log assertions.</violation>
</file>

<file name="scripts/hooks/pre-push">

<violation number="1" location="scripts/hooks/pre-push:1">
P3: The new pre-push source file is committed without the executable bit (mode 644), unlike scripts/hooks/pre-commit (755). The installer chmods the installed copy so the primary path works, but any direct execution of the in-tree hook (e.g. core.hooksPath pointing at scripts/hooks, or invoking it manually/from CI) silently fails; set the executable bit on the committed file to match pre-commit.</violation>
</file>

<file name="scripts/lib/mcb.sh">

<violation number="1" location="scripts/lib/mcb.sh:59">
P2: Repositories with `core.hooksPath` configured install hooks into the unused default directory, leaving the advertised pre-commit enforcement inactive; resolve and honor the configured hooks path before copying.</violation>

<violation number="2" location="scripts/lib/mcb.sh:81">
P1: `make sub WHAT=sync` loops forever on POSIX `/bin/sh` systems because `git submodule foreach` cannot execute Bash's `read -d`; use a POSIX-compatible path reader or explicitly invoke Bash for this pipeline.</violation>

<violation number="3" location="scripts/lib/mcb.sh:82">
P1: A submodule with one remaining tracked file is treated as materialized, so `sync-submodules` leaves other deleted tracked files missing; check every indexed path and restore only missing paths to preserve local edits.</violation>

<violation number="4" location="scripts/lib/mcb.sh:137">
P1: Commits that stage Cargo.toml/Cargo.lock will fail the staged check. When a manifest/lockfile is staged, `packages` is set to `--workspace` and fed to `cargo fmt $packages -- --check`, but `cargo fmt` does not accept `--workspace` (only `-p/--package` and `--all`), so it exits 2 and the pre-commit gate aborts. `cargo clippy` does accept `--workspace`, which is why the mismatch only surfaces on the fmt call. Use a scope flag that both tools accept (e.g. `--all`) or split fmt/clippy scoping.</violation>

<violation number="5" location="scripts/lib/mcb.sh:141">
P2: Manifest, build-script, and non-`src` target changes skip the staged fmt/clippy gate entirely; include those crate paths when deriving `packages` so `--all-targets` covers the staged change.</violation>

<violation number="6" location="scripts/lib/mcb.sh:155">
P1: The pre-commit gate validates unstaged working-tree contents rather than the staged snapshot, allowing invalid staged Rust to pass after an unstaged local fix; run checks against an index materialization or reject relevant unstaged changes.</violation>
</file>

Shadow auto-approve: would not auto-approve because issues were found.

Re-trigger cubic

from pathlib import Path
from typing import NoReturn

import toml

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: Every dispatcher invocation fails at import when its required toml package is not preinstalled; declare and provision this runtime dependency for the workspace Python environment.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At scripts/lib/workspace_command.py, line 20:

<comment>Every dispatcher invocation fails at import when its required `toml` package is not preinstalled; declare and provision this runtime dependency for the workspace Python environment.</comment>

<file context>
@@ -0,0 +1,778 @@
+from pathlib import Path
+from typing import NoReturn
+
+import toml
+
+from lib.workspace import (
</file context>

Comment thread scripts/lib/mcb.sh
[ -n "$staged" ] || { mcb_ok "staged check: no staged paths"; return 0; }

if printf '%s\n' "$staged" | grep -qE '^Cargo\.(toml|lock)$'; then
packages="--workspace"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: Commits that stage Cargo.toml/Cargo.lock will fail the staged check. When a manifest/lockfile is staged, packages is set to --workspace and fed to cargo fmt $packages -- --check, but cargo fmt does not accept --workspace (only -p/--package and --all), so it exits 2 and the pre-commit gate aborts. cargo clippy does accept --workspace, which is why the mismatch only surfaces on the fmt call. Use a scope flag that both tools accept (e.g. --all) or split fmt/clippy scoping.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At scripts/lib/mcb.sh, line 137:

<comment>Commits that stage Cargo.toml/Cargo.lock will fail the staged check. When a manifest/lockfile is staged, `packages` is set to `--workspace` and fed to `cargo fmt $packages -- --check`, but `cargo fmt` does not accept `--workspace` (only `-p/--package` and `--all`), so it exits 2 and the pre-commit gate aborts. `cargo clippy` does accept `--workspace`, which is why the mismatch only surfaces on the fmt call. Use a scope flag that both tools accept (e.g. `--all`) or split fmt/clippy scoping.</comment>

<file context>
@@ -77,6 +125,38 @@ mcb_validate() {  # $1 = "quick" | "full"
+  [ -n "$staged" ] || { mcb_ok "staged check: no staged paths"; return 0; }
+
+  if printf '%s\n' "$staged" | grep -qE '^Cargo\.(toml|lock)$'; then
+    packages="--workspace"
+  else
+    while IFS= read -r path; do
</file context>

Comment thread scripts/lib/mcb.sh

[ -n "$packages" ] || { mcb_ok "staged check: no Rust package affected"; return 0; }
mcb_log "staged check: cargo fmt/clippy scope:$packages (deadline ${deadline}s each)"
timeout --signal=TERM --kill-after=5s "${deadline}s" cargo fmt $packages -- --check

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: The pre-commit gate validates unstaged working-tree contents rather than the staged snapshot, allowing invalid staged Rust to pass after an unstaged local fix; run checks against an index materialization or reject relevant unstaged changes.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At scripts/lib/mcb.sh, line 155:

<comment>The pre-commit gate validates unstaged working-tree contents rather than the staged snapshot, allowing invalid staged Rust to pass after an unstaged local fix; run checks against an index materialization or reject relevant unstaged changes.</comment>

<file context>
@@ -77,6 +125,38 @@ mcb_validate() {  # $1 = "quick" | "full"
+
+  [ -n "$packages" ] || { mcb_ok "staged check: no Rust package affected"; return 0; }
+  mcb_log "staged check: cargo fmt/clippy scope:$packages (deadline ${deadline}s each)"
+  timeout --signal=TERM --kill-after=5s "${deadline}s" cargo fmt $packages -- --check
+  timeout --signal=TERM --kill-after=5s "${deadline}s" cargo clippy $packages --all-targets -- -D warnings
+  mcb_ok "staged check: clean"
</file context>

Comment thread scripts/lib/mcb.sh
Comment on lines +81 to +86
present="$(git ls-files -z | while IFS= read -r -d "" path; do
if [ -e "$path" ] || [ -L "$path" ]; then
printf 1
break
fi
done)"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: make sub WHAT=sync loops forever on POSIX /bin/sh systems because git submodule foreach cannot execute Bash's read -d; use a POSIX-compatible path reader or explicitly invoke Bash for this pipeline.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At scripts/lib/mcb.sh, line 81:

<comment>`make sub WHAT=sync` loops forever on POSIX `/bin/sh` systems because `git submodule foreach` cannot execute Bash's `read -d`; use a POSIX-compatible path reader or explicitly invoke Bash for this pipeline.</comment>

<file context>
@@ -51,6 +51,54 @@ mcb_retry() { local n="$1" s="$2"; shift 2; local t=1; while ! "$@"; do [ "$t" -
+
+  while :; do
+    materialized="$(git -C "$repo" submodule foreach --quiet --recursive '
+      present="$(git ls-files -z | while IFS= read -r -d "" path; do
+        if [ -e "$path" ] || [ -L "$path" ]; then
+          printf 1
</file context>
Suggested change
present="$(git ls-files -z | while IFS= read -r -d "" path; do
if [ -e "$path" ] || [ -L "$path" ]; then
printf 1
break
fi
done)"
present="$(git ls-files | while IFS= read -r path; do
if [ -e "$path" ] || [ -L "$path" ]; then
printf 1
break
fi
done)"

Comment thread scripts/lib/mcb.sh
while :; do
materialized="$(git -C "$repo" submodule foreach --quiet --recursive '
present="$(git ls-files -z | while IFS= read -r -d "" path; do
if [ -e "$path" ] || [ -L "$path" ]; then

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: A submodule with one remaining tracked file is treated as materialized, so sync-submodules leaves other deleted tracked files missing; check every indexed path and restore only missing paths to preserve local edits.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At scripts/lib/mcb.sh, line 82:

<comment>A submodule with one remaining tracked file is treated as materialized, so `sync-submodules` leaves other deleted tracked files missing; check every indexed path and restore only missing paths to preserve local edits.</comment>

<file context>
@@ -51,6 +51,54 @@ mcb_retry() { local n="$1" s="$2"; shift 2; local t=1; while ! "$@"; do [ "$t" -
+  while :; do
+    materialized="$(git -C "$repo" submodule foreach --quiet --recursive '
+      present="$(git ls-files -z | while IFS= read -r -d "" path; do
+        if [ -e "$path" ] || [ -L "$path" ]; then
+          printf 1
+          break
</file context>

Comment thread scripts/hooks/pre-commit
echo "→ guard (staged)…"; bash scripts/lib/mcb.sh guard --staged
echo "→ lint…"; make check WHAT=lint
echo "→ validate (quick)…"; make check WHAT=validate QUICK=1
echo "→ staged check…"; make check WHAT=staged

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: Published pre-commit instructions still promise lint and architecture validation; update them to describe the staged-only gate so developers do not rely on checks this hook no longer runs.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At scripts/hooks/pre-commit, line 10:

<comment>Published pre-commit instructions still promise lint and architecture validation; update them to describe the staged-only gate so developers do not rely on checks this hook no longer runs.</comment>

<file context>
@@ -1,11 +1,11 @@
 echo "→ guard (staged)…";   bash scripts/lib/mcb.sh guard --staged
-echo "→ lint…";             make check WHAT=lint
-echo "→ validate (quick)…"; make check WHAT=validate QUICK=1
+echo "→ staged check…";      make check WHAT=staged
 echo "✓ pre-commit passed"
</file context>

Comment thread Makefile

# --- WHATS_<verb> phase SSOT (drives sub-help + error arms) -------------------
WHATS_check := fmt lint validate audit udeps coverage qlty all
WHATS_check := fmt lint staged validate audit udeps coverage qlty hooks guard all

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: The new check phases (staged/hooks/guard) are not reflected in AGENTS.md/README.md, which still list check WHAT as fmt|lint|validate|audit|udeps|coverage|qlty|all. Since those docs are embedded as agent/reviewer context, updating them keeps the documented surface in sync with the fact that the phases already work here.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At Makefile, line 39:

<comment>The new check phases (staged/hooks/guard) are not reflected in AGENTS.md/README.md, which still list check WHAT as fmt|lint|validate|audit|udeps|coverage|qlty|all. Since those docs are embedded as agent/reviewer context, updating them keeps the documented surface in sync with the fact that the phases already work here.</comment>

<file context>
@@ -36,7 +36,7 @@ export RUST_2024_LINTS := -D unsafe_op_in_unsafe_fn -D rust_2024_compatibility -
 
 # --- WHATS_<verb> phase SSOT (drives sub-help + error arms) -------------------
-WHATS_check   := fmt lint validate audit udeps coverage qlty all
+WHATS_check   := fmt lint staged validate audit udeps coverage qlty hooks guard all
 WHATS_fix     := fmt lint docs all
 WHATS_dev     := run docker-up docker-down docker-logs docker-test
</file context>

#!/usr/bin/env bash
while [ "$#" -gt 0 ]; do
case "$1" in
--signal=*|--kill-after=*|*[smhd]) shift ;;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: The timeout stub's *[smhd] pattern swallows any argument ending in s/m/h/d, not only the duration token. It only works because cargo is always the first word after the timeout options, so consider narrowing the match to duration-shaped args (e.g. *[0-9][smhd]) so a future reorder or option doesn't silently drop a real argument and skew the log assertions.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At scripts/lib/tests/test-hooks.sh, line 71:

<comment>The `timeout` stub's `*[smhd]` pattern swallows any argument ending in s/m/h/d, not only the duration token. It only works because `cargo` is always the first word after the timeout options, so consider narrowing the match to duration-shaped args (e.g. `*[0-9][smhd]`) so a future reorder or option doesn't silently drop a real argument and skew the log assertions.</comment>

<file context>
@@ -0,0 +1,130 @@
+#!/usr/bin/env bash
+while [ "$#" -gt 0 ]; do
+  case "$1" in
+    --signal=*|--kill-after=*|*[smhd]) shift ;;
+    *) break ;;
+  esac
</file context>

Comment thread scripts/hooks/pre-push
@@ -0,0 +1,10 @@
#!/usr/bin/env bash

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: The new pre-push source file is committed without the executable bit (mode 644), unlike scripts/hooks/pre-commit (755). The installer chmods the installed copy so the primary path works, but any direct execution of the in-tree hook (e.g. core.hooksPath pointing at scripts/hooks, or invoking it manually/from CI) silently fails; set the executable bit on the committed file to match pre-commit.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At scripts/hooks/pre-push, line 1:

<comment>The new pre-push source file is committed without the executable bit (mode 644), unlike scripts/hooks/pre-commit (755). The installer chmods the installed copy so the primary path works, but any direct execution of the in-tree hook (e.g. core.hooksPath pointing at scripts/hooks, or invoking it manually/from CI) silently fails; set the executable bit on the committed file to match pre-commit.</comment>

<file context>
@@ -0,0 +1,10 @@
+#!/usr/bin/env bash
+# Installed by `make setup WHAT=hooks`. Runs the canonical full gate before
+# push, then preserves Beads hook processing when available.
</file context>

if args and args[0] == "--validate":
return 0
if not args or args[0] in {"help", "--help", "-h"}:
os.environ.get("WHAT", "").strip()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: This statement is a no-op: it calls os.environ.get("WHAT", "").strip() and discards the result. It looks like a leftover line from an earlier help-rendering draft, and the very next line returns 0, so this has zero effect. Safe to delete.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At scripts/lib/workspace_command.py, line 185:

<comment>This statement is a no-op: it calls `os.environ.get("WHAT", "").strip()` and discards the result. It looks like a leftover line from an earlier help-rendering draft, and the very next line returns 0, so this has zero effect. Safe to delete.</comment>

<file context>
@@ -0,0 +1,778 @@
+        if args and args[0] == "--validate":
+            return 0
+        if not args or args[0] in {"help", "--help", "-h"}:
+            os.environ.get("WHAT", "").strip()
+            return 0
+        return dispatch(registry, args[0])
</file context>

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0 issues found across 1 file (changes from recent commits).

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.

Shadow auto-approve: would not auto-approve. Auto-approval blocked by 17 unresolved issues from previous reviews.

Re-trigger cubic

@marlon-costa-dc

Copy link
Copy Markdown
Collaborator Author

Closed: associated bead already resolved via recovery lane (21c9d7f). Branch work was absorbed or superseded.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant